package com.aiyan.edu.service.search.service;

import com.aiyan.edu.framework.domain.course.CoursePlanMediaPub;
import com.aiyan.edu.framework.domain.course.CoursePub;
import com.aiyan.edu.framework.domain.search.CourseSearchParam;
import com.aiyan.edu.framework.model.response.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author: zqzhou
 * @create: 2019/11/13 11:54
 **/
@Service
public class CourseEsService {

    private static final Logger LOGGER = LoggerFactory.getLogger(CourseEsService.class);

    @Value("${es.course.index}")
    private String esCourseIndex;

    @Value("${es.course-plan-media.index}")
    private String esCoursePlanMediaIndex;

    private String sourceFileds = "id,name,grade,mt,st,charge,valid,pic,qq,price,price_old,status,study_model,teach_mode,expires,pub_time,start_time,end_time";

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    /**
     * 查询课程列表
     *
     * @param page
     * @param size
     * @param courseSearchParam
     * @return
     */
    public QueryResponseResult<CoursePub> findList(int page, int size, CourseSearchParam courseSearchParam) {
        SearchRequest searchRequest = new SearchRequest(this.esCourseIndex);

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        // source字段过滤
        String[] sourceFiledsArr = this.sourceFileds.split(",");
        searchSourceBuilder.fetchSource(sourceFiledsArr, new String[]{});

        //匹配关键字
        if (StringUtils.isNotEmpty(courseSearchParam.getKeyword())) {
            MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(courseSearchParam.getKeyword(), "name", "course_plan", "description");
            //设置匹配占比
            multiMatchQueryBuilder.minimumShouldMatch("70%");
            //提升另个字段的Boost值
            multiMatchQueryBuilder.field("name", 10);
            boolQueryBuilder.must(multiMatchQueryBuilder);
        }

        // 过滤课程分类和难度等级
        if (StringUtils.isNotEmpty(courseSearchParam.getMt())) {
            boolQueryBuilder.filter(QueryBuilders.termQuery("mt", courseSearchParam.getMt()));
        }

        if (StringUtils.isNotEmpty(courseSearchParam.getSt())) {
            boolQueryBuilder.filter(QueryBuilders.termQuery("st", courseSearchParam.getSt()));
        }

        if (StringUtils.isNotEmpty(courseSearchParam.getGrade())) {
            boolQueryBuilder.filter(QueryBuilders.termQuery("grade", courseSearchParam.getGrade()));
        }

        if (page <= 0) {
            page = 1;
        }
        if (size <= 0) {
            size = 20;
        }
        int start = (page - 1) * size;

        // 分页查询
        searchSourceBuilder.from(start);
        searchSourceBuilder.size(size);

        //布尔查询
        searchSourceBuilder.query(boolQueryBuilder);
        //请求搜索
        searchRequest.source(searchSourceBuilder);

        SearchResponse searchResponse = null;

        try {
            searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

        } catch (IOException e) {
            e.printStackTrace();
            this.LOGGER.error("search error..{}", e.getMessage());
            return new QueryResponseResult(CommonCode.SUCCESS, new QueryResult<CoursePub>());
        }

        // 处理结果集
        SearchHits searchHits = searchResponse.getHits();
        SearchHit[] hits = searchHits.getHits();

        List<CoursePub> list = new ArrayList<>();

        for (SearchHit hit : hits) {
            CoursePub coursePub = new CoursePub();

            //取出source
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();

            coursePub.setName(sourceAsMap.get("name").toString());
            coursePub.setPic(sourceAsMap.get("pic").toString());
            Double price = null;
            try {
                if (sourceAsMap.get("price") != null) {
                    price = (Double) sourceAsMap.get("price");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            coursePub.setPrice(price);
            Double price_old = null;
            try {
                if (sourceAsMap.get("price_old") != null) {
                    price_old = (Double) sourceAsMap.get("price_old");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            coursePub.setPriceOld(price_old);
            //"id,name,grade,mt,st,charge,valid,pic,qq,price,price_old,status,study_model,teach_mode,expires,pub_time,start_time,end_time"
            if (sourceAsMap.get("grade") != null) {
                coursePub.setGrade(sourceAsMap.get("grade").toString());
            }
            if (sourceAsMap.get("mt") != null) {
                coursePub.setMt(sourceAsMap.get("mt").toString());
            }
            if (sourceAsMap.get("st") != null) {
                coursePub.setSt(sourceAsMap.get("st").toString());
            }
            if (sourceAsMap.get("charge") != null) {
                coursePub.setCharge(sourceAsMap.get("charge").toString());
            }
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            if (sourceAsMap.get("expires") != null) {
//                try {
//                    coursePub.setExpires(sdf.parse(sourceAsMap.get("expires").toString()));
//                } catch (ParseException e) {
//                    e.printStackTrace();
//                }
            }
            if (sourceAsMap.get("qq") != null) {
                coursePub.setQq(sourceAsMap.get("qq").toString());
            }
            if (sourceAsMap.get("study_model") != null) {
                coursePub.setStudyModel(sourceAsMap.get("study_model").toString());
            }
            if (sourceAsMap.get("teach_mode") != null) {
                coursePub.setTeachMode(sourceAsMap.get("teach_mode").toString());
            }
            if (sourceAsMap.get("id") != null) {
                coursePub.setId(sourceAsMap.get("id").toString());
            }
            if (sourceAsMap.get("pub_time") != null) {
//                try {
//                    coursePub.setPubTime(sdf.parse(sourceAsMap.get("pub_time").toString()));
//                } catch (ParseException e) {
//                    e.printStackTrace();
//                }
            }

            list.add(coursePub);
        }
        QueryResult<CoursePub> queryResult = new QueryResult<>();
        queryResult.setList(list);
        queryResult.setTotal(searchHits.getTotalHits().value);
        QueryResponseResult<CoursePub> coursePubQueryResponseResult = new
                QueryResponseResult<CoursePub>(CommonCode.SUCCESS, queryResult);
        return coursePubQueryResponseResult;
    }

    /**
     * 搜索课程详情
     *
     * @param id
     * @return
     */
    public CommonResponseResult<CoursePub> find(String id) {
        SearchRequest searchRequest = new SearchRequest(this.esCourseIndex);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.termQuery("id", id));
        searchRequest.source(searchSourceBuilder);

        SearchResponse searchResponse = null;
        try {
            searchResponse = this.restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        } catch (Exception e) {
            e.printStackTrace();
        }

        SearchHits searchHits = searchResponse.getHits();
        SearchHit[] hits = searchHits.getHits();
        if (hits.length == 0) {
            return new CommonResponseResult<>(CommonCode.SUCCESS, null);
        }

        Map<String, Object> sourceAsMap = hits[0].getSourceAsMap();
        String name = (String) sourceAsMap.get("name");
        String grade = (String) sourceAsMap.get("grade");
        String charge = (String) sourceAsMap.get("charge");
        String pic = (String) sourceAsMap.get("pic");
        String description = (String) sourceAsMap.get("description");
        String coursePlan = (String) sourceAsMap.get("course_plan");
        CoursePub coursePub = new CoursePub();
        coursePub.setId(id);
        coursePub.setName(name);
        coursePub.setPic(pic);
        coursePub.setGrade(grade);
        coursePub.setCharge(charge);
        coursePub.setCoursePlan(coursePlan);
        coursePub.setDescription(description);

        return new CommonResponseResult<>(CommonCode.SUCCESS, coursePub);
    }

    /**
     * 查询课程计划媒资
     *
     * @param coursePlanIds
     * @return
     */
    public QueryResponseResult<CoursePlanMediaPub> findCourseMedia(String... coursePlanIds) {
        SearchRequest searchRequest = new SearchRequest(this.esCoursePlanMediaIndex);

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.termsQuery("course_plan_id", coursePlanIds));

        searchRequest.source(searchSourceBuilder);

        SearchResponse searchResponse = null;

        try {
            searchResponse = this.restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }

        SearchHits responseHits = searchResponse.getHits();
        SearchHit[] hits = responseHits.getHits();

        List<CoursePlanMediaPub> result = new ArrayList<>();

        for (SearchHit hit : hits) {
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();

            CoursePlanMediaPub coursePlanMediaPub = new CoursePlanMediaPub();
            coursePlanMediaPub.setCourseId(sourceAsMap.get("course_id").toString());
            coursePlanMediaPub.setCoursePlanId(sourceAsMap.get("course_plan_id").toString());
            coursePlanMediaPub.setMediaFileOriginalName(sourceAsMap.get("media_file_original_name").toString());
            coursePlanMediaPub.setMediaId(sourceAsMap.get("media_id").toString());
            coursePlanMediaPub.setMediaUrl(sourceAsMap.get("media_url").toString());

            result.add(coursePlanMediaPub);
        }

        QueryResult<CoursePlanMediaPub> queryResult = new QueryResult<>();
        queryResult.setList(result);
        queryResult.setTotal(result.size());

        return new QueryResponseResult<>(CommonCode.SUCCESS, queryResult);
    }
}
